package com.px.user.security;

import com.px.common.core.RespCode;
import com.px.common.core.RespException;
import com.px.common.util.JsonUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

import static com.px.common.security.AuthConst.TOKEN_HEADER;


public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader(TOKEN_HEADER);
        if (StringUtils.isEmpty(token))
            throw new RespException(RespCode.TOKEN_ERROR, null);

        try{
            Jwt jwt = JwtHelper.decode(token);
            Map claims = JsonUtil.fromJson(jwt.getClaims(), Map.class);
            long exp = Long.valueOf((String) claims.get("exp"));
            if (exp < new Date().getTime() / 1000)
                throw new RespException(RespCode.TOKEN_EXPIRE, token);
        }catch (Exception e){
            throw new RespException(RespCode.TOKEN_ERROR, token);
        }
        Authentication auth = new TokenAuthentication(token);
        SecurityContextHolder.getContext().setAuthentication(auth);
        request.setAttribute("TokenAuthenticationFilter.FILTERED", true);
        filterChain.doFilter(request, response);
    }

    class TokenAuthentication implements Authentication {
        private String token;

        private TokenAuthentication(String token) {
            this.token = token;
        }

        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return null;
        }

        @Override
        public Object getCredentials() {
            return token;
        }

        @Override
        public Object getDetails() {
            return null;
        }

        @Override
        public Object getPrincipal() {
            return null;
        }

        @Override
        public boolean isAuthenticated() {
            return false;
        }

        @Override
        public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
        }

        @Override
        public String getName() {
            return "token";
        }
    }
}
